# /**
# * @File        Makefile
# * @Author      Jiri Jaros
# *              Faculty of Information Technology
# *              Brno University of Technology 
# * @Email       jarosjir@fit.vutbr.cz
# * @Comments    Linux makefile for Ubuntu 14.04
# * 
# * @Tool        kspaceFirstOrder3D 3.4
# * @Created     02 December  2014, 12:32 
# * @LastModif   02 August    2016, 15:49
#
# * @License: 
# * This file is part of the C++ extension of the k-Wave Toolbox
# * (http://www.k-wave.org).\n Copyright (C) 2016 Jiri Jaros and Bradley Treeby
# * 
# * This file is part of the k-Wave. k-Wave is free software: you can redistribute it 
# * and/or modify it under the terms of the GNU Lesser General Public License as 
# * published by the Free Software Foundation, either version 3 of the License, 
# * or (at your option) any later version.
# * 
# * k-Wave is distributed in the hope that it will be useful, but 
# * WITHOUT ANY WARRANTY; without even the implied warranty of 
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
# * See the GNU Lesser General Public License for more details. 
# * 
# * You should have received a copy of the GNU Lesser General Public License 
# * along with k-Wave. If not, see <http://www.gnu.org/licenses/>.
# */

#################################################################################
#	The source codes can be compiled ONLY under Linux x64 			#
#	by GNU g++ 4.8 and newer OR Intel Compiler icpc 14 and newer 		#
#	The newer compiler, the more advanced instruction set can be used	#
#	We recomend compilation with g++ 4.8/4.9 or icpc 14/15                  #
#                                                                               #
#       The code also requires CUDA 7.5, but can work with CUDA 7.0 and 6.5     #
#       With older CUDA versons, it is necessary to remove unknown              #
#       architectures.                                                          #
#                                                                               #
#	The code requires compilator suporitng C++-11 standard!			#
#	The code uses GNU compiler and STATIC linking by default		#
#										#
#	Necessary libraries:							#
#		- HDF5 version 1.8 and newer					#
#										#
#	How to compile libraries						#
#		- CUDA : download from                                          #
#                           "https://developer.nvidia.com/downloads             #
#		- HDF5 : download from http://www.hdfgroup.org/HDF5/ 		#
#			run configure script with these parameters:	        #
#			--enable-hl --enable-static --enable-shared     	#
#									      	#
#	This makefile enables static and dynamic compilation using 		#
#									      	#
#################################################################################


#################################################################################
#	  Set following flags based on your compiler and library paths 		#
#################################################################################


# static lining is deafult
LINKING = STATIC
#LINKING = DYNAMIC

#Set up paths: find HDF5
HDF5_DIR=/usr/local/hdf5-serial
CUDA_DIR=/usr/local/cuda
    
#Get GIT hash (only if you build form Gitlab repository)
#KWAVE_GIT_HASH=$(shell git rev-parse HEAD)
#Otherwise, use the last official build hash
KWAVE_GIT_HASH=21781e5c61d42046de07a12f36dc15cb89a0581f
#################################################################################


############################## NVCC + GNU g++ ###################################
CXX = nvcc
 

# Set compiler flags and header files directories
CXXFLAGS = -Xcompiler="-Wall -O3 -fopenmp -ffast-math -fassociative-math "\
           -O3 -std=c++11  -I$(HDF5_DIR)/include  -I.  --restrict \
	   -D__KWAVE_GIT_HASH__=\"$(KWAVE_GIT_HASH)\"  \
	   --generate-code arch=compute_20,code=sm_20	\
	   --generate-code arch=compute_20,code=sm_21	\
	   --generate-code arch=compute_30,code=sm_30	\
	   --generate-code arch=compute_32,code=sm_32	\
	   --generate-code arch=compute_35,code=sm_35	\
	   --generate-code arch=compute_37,code=sm_37	\
	   --generate-code arch=compute_50,code=sm_50	\
	   --generate-code arch=compute_52,code=sm_52	\
	   --generate-code arch=compute_53,code=sm_53	\
	   --device-c

  
LDFLAGS  =  -Xcompiler="-fopenmp" \
	    -Xlinker="-rpath,$(HDF5_DIR)/lib:$(CUDA_DIR)/lib64" -std=c++11  -L$(HDF5_DIR)/lib  -L$(CUDA_DIR)/lib64 

ifeq ($(LINKING),STATIC)

	LIBS  = $(HDF5_DIR)/lib/libhdf5_hl.a 	\
            	$(HDF5_DIR)/lib/libhdf5.a		\
	        $(CUDA_DIR)/lib64/libcufft_static.a \
	        $(CUDA_DIR)/lib64/libculibos.a \
	        $(CUDA_DIR)/lib64/libculibos.a \
        	$(CUDA_DIR)/lib64/libcudart_static.a \
	        -lz -ldl
endif

ifeq ($(LINKING),DYNAMIC)
	LIBS     = -lhdf5 -lhdf5_hl -lz -lcufft 
endif
  

################################# Compile #####################################

TARGET		= kspaceFirstOrder3D-CUDA

all:		$(TARGET)	


$(TARGET):	Containers/MatrixContainer.o \
		Containers/MatrixRecord.o \
		Containers/OutputStreamContainer.o \
		HDF5/HDF5_File.o \
		KSpaceSolver/KSpaceFirstOrder3DSolver.o \
		KSpaceSolver/SolverCUDAKernels.o \
		Logger/Logger.o	\
		MatrixClasses/BaseFloatMatrix.o \
		MatrixClasses/BaseIndexMatrix.o \
		MatrixClasses/CUFFTComplexMatrix.o \
		MatrixClasses/ComplexMatrix.o \
		MatrixClasses/IndexMatrix.o \
		MatrixClasses/RealMatrix.o \
		OutputHDF5Streams/BaseOutputHDF5Stream.o \
		OutputHDF5Streams/IndexOutputHDF5Stream.o \
		OutputHDF5Streams/CuboidOutputHDF5Stream.o \
		OutputHDF5Streams/WholeDomainOutputHDF5Stream.o \
		OutputHDF5Streams/OutputStreamsCUDAKernels.o \
		Parameters/CommandLineParameters.o \
		Parameters/Parameters.o \
		Parameters/CUDAParameters.o \
		Parameters/CUDADeviceConstants.o \
		main.o


	$(CXX) $(LDFLAGS) main.o	\
		Containers/MatrixContainer.o \
		Containers/MatrixRecord.o \
		Containers/OutputStreamContainer.o \
		HDF5/HDF5_File.o \
		KSpaceSolver/KSpaceFirstOrder3DSolver.o \
		KSpaceSolver/SolverCUDAKernels.o \
		Logger/Logger.o	\
		MatrixClasses/BaseFloatMatrix.o \
		MatrixClasses/BaseIndexMatrix.o \
		MatrixClasses/CUFFTComplexMatrix.o \
		MatrixClasses/ComplexMatrix.o \
		MatrixClasses/IndexMatrix.o \
		MatrixClasses/RealMatrix.o \
		OutputHDF5Streams/BaseOutputHDF5Stream.o \
		OutputHDF5Streams/IndexOutputHDF5Stream.o \
		OutputHDF5Streams/CuboidOutputHDF5Stream.o \
		OutputHDF5Streams/WholeDomainOutputHDF5Stream.o \
		OutputHDF5Streams/OutputStreamsCUDAKernels.o \
		Parameters/CommandLineParameters.o \
		Parameters/Parameters.o \
		Parameters/CUDAParameters.o \
		Parameters/CUDADeviceConstants.o \
		$(LIBS)			\
		-o $@

$(TARGET).o : $(TARGET).cpp 
	$(CXX) $(CXXFLAGS) -c $(TARGET).cpp 


KSpaceSolver/SolverCUDAKernels.o : KSpaceSolver/SolverCUDAKernels.cu
	$(CXX) $(CXXFLAGS) -c KSpaceSolver/SolverCUDAKernels.cu -o KSpaceSolver/SolverCUDAKernels.o

OutputHDF5Streams/OutputStreamsCUDAKernels.o : OutputHDF5Streams/OutputStreamsCUDAKernels.cu
	$(CXX) $(CXXFLAGS) -c OutputHDF5Streams/OutputStreamsCUDAKernels.cu -o OutputHDF5Streams/OutputStreamsCUDAKernels.o

Parameters/CUDADeviceConstants.o \ : Parameters/CUDADeviceConstants.cu
	$(CXX) $(CXXFLAGS) -c Parameters/CUDADeviceConstants.cu -o Parameters/CUDADeviceConstants.o

clean:
	rm -f *.o HDF5/*.o KSpaceSolver/*.o MatrixClasses/*.o Parameters/*.o Containers/*.o  OutputHDF5Streams/*.o Logger/*.o $(TARGET)
